﻿using CKS.Core.Framework;
using CKS.PLC.Action.Subscription;
using CKS.PLC.Action.Sys;
using FreeSql;
using Infrastructure;
using Mapster;
using Microsoft.Extensions.DependencyInjection;

using ZR.Model.Models.ProductionControl;

namespace CKS.PLC.Action
{
    /// <summary>
    /// 订阅动作基类
    /// 可根据不同项目自行定义ActionId
    /// </summary>
    public abstract partial class PLCAction : BasePlcAction
    {
        protected PLCAction(DecodeValue _value) : base(_value)
        {
        }
        /// 如果多个站 每个站的每个DB文件的操作编号可以相同。
        /// 根据工站编号 - DB块 - 操作编号类
        /// 程序目录示例： OP50/DB3011/CKS01Action.cs、OP60/DB3010/CKS01Action.cs
        //  流程action 1 - 100 
        //              1 请求加工 2请求保存    
        //  纯数据 101 - 200

        /*
         插件式：每次执行前检查DLL是否发生变化，
            1.有变化则更新缓存程序集
            2.从缓存程序集提取实例执行
         */
        // var value = (DecodeValue)dv;
        //GetInstance
        //GetInstance
        public static PLCAction GetInstance(DecodeValue value)
        {
            var position = value.Position;
            if (position.EffectType == 5)
                return new SaveProcessingResults(value);
            if (position.EffectType == 6)
            {
                new SaveProcessingResults(value).Execute();
            }

            if(position.EffectType == 4 && value.Position.ActionKey == "oee")
            {
                return new SaveDeviceStatusLogAction(value);
            }


            switch (position.PlcId)
            {
                case 1:
                    return GetOP10ActionInstance(value);
                case 2:
                    return GetOP20ActionInstance(value);
                case 3:
                    return GetOP30ActionInstance(value);
                case 5:
                    return GetOP50ActionInstance(value);
                case 6:
                    return GetOP60ActionInstance(value);
                case 7:
                    return GetOP70ActionInstance(value);
                case 8:
                    return GetOP80ActionInstance(value);
                case 9:
                    return GetOP90ActionInstance(value);
                case 10:
                    return GetOP100ActionInstance(value);
                case 11:
                    return GetOP110ActionInstance(value);
                case 12:
                    return GetOP120ActionInstance(value);
                case 13:
                    return GetOP130ActionInstance(value);
                case 14:
                    return GetOP140ActionInstance(value);
                default:
                    throw new InvalidOperationException("当前工位编号逻辑尚未添加");
            }



            //switch (value.Position.ActionId)
            //{
            //    case 9999:
            //        return new Test00Action(value);
            //    case 1:
            //        return new Cks01Action(value);
            //    default:
            //        throw new InvalidOperationException("未实现的操作编号");
            //}
        }

        private static PLCAction GetOP120ActionInstance(DecodeValue value)
        {
            var position = value.Position;
            switch (position.ActionId)
            {
                case 301:
                    return new Subscription.OP120.MergeCodeAction(value);
                default:
                    throw new InvalidOperationException("未实现的操作编号");
            }
        }

        private static PLCAction GetOP50ActionInstance(DecodeValue value)
        {
            var position = value.Position;
            switch (position.ActionId)
            {
                case 1:
                    return new Subscription.OP50.OP50SaveDataAction(value);
                case 2:
                    return new Subscription.OP50.DB3021_Work02Action(value);
                case 3:
                    return new Subscription.OP50.DB3021_Work03Action(value);
                default:
                    throw new InvalidOperationException("未实现的操作编号");
            }
        }

        private static PLCAction GetOP90ActionInstance(DecodeValue value)
        {
            var position = value.Position;
            switch (position.ActionId)
            {
                case 1:
                    return new Subscription.OP90.DB3011_Work01Action(value);
                case 2:
                    return new Subscription.OP90.DB3011_Work02Action(value);
                case 3:
                    return new Subscription.OP90.DB3011_Work03Action(value);
                default:
                    throw new InvalidOperationException("未实现的操作编号");
            }
        }

        private static PLCAction GetOP100ActionInstance(DecodeValue value)
        {
            var position = value.Position;
            switch (position.ActionId)
            {
                case 1:
                    return new Subscription.OP100.DB3011_Work01Action(value);
                default:
                    throw new InvalidOperationException("未实现的操作编号");
            }
        }

        private static PLCAction GetOP110ActionInstance(DecodeValue value)
        {
            var position = value.Position;
            switch (position.ActionId)
            {
                case 1:
                    return new Subscription.OP110.DB3011_Work01Action(value);
                default:
                    throw new InvalidOperationException("未实现的操作编号");
            }
        }

        private static PLCAction GetOP140ActionInstance(DecodeValue value)
        {
            var position = value.Position;
            switch (position.ActionId)
            {
                case 1:
                    return new Subscription.OP140.DB3011_Work01Action(value);
                default:
                    throw new InvalidOperationException("未实现的操作编号");
            }
        }

        private static PLCAction GetOP10ActionInstance(DecodeValue value)
        {
            var position = value.Position;
            switch (position.ActionId)
            {
                case 1: //入口错误
                case 2: //使用次数达到报警
                    return new OP10.Cks01Action(value);
                case 30:
                    return new OP10.Cks30Action(value);
                case 101:
                    return new OP10.Cks101Action(value);
                case 102:
                    return new OP10.Cks102Action(value);
                case 201:
                    return new OP10.Cks201Action(value);
                case 202:
                    return new OP10.Cks202Action(value);
                case 203:
                    return new OP10.Cks203Action(value);
                case 204:
                    return new OP10.Cks204Action(value);
                default:
                    throw new InvalidOperationException("未实现的操作编号");
            }
        }

        private static PLCAction GetOP80ActionInstance(DecodeValue value)
        {
            var position = value.Position;

            //如果DB块是1200 特殊处理
            switch (position.ActionId)
            {
                case 1:
                    if (position.BlockDb == 3021)
                        return new Subscription.OP80.DB3021_Work01Action(value);
                    else if (position.BlockDb == 3031)
                        return new Subscription.OP80.DB3031_Work01Action(value);
                    else if (position.BlockDb == 3041)
                        return new Subscription.OP80.DB3041_Work01Action(value);
                    else
                        throw new InvalidOperationException("未实现的DB");
                case 101:
                    return new Subscription.OP80.DB3011_Work101Action(value);
                case 102:
                    return new Subscription.OP80.DB3011_Work102Action(value);
                case 201:
                    return new Subscription.OP80.DB3011_Work201Action(value);
                case 202:
                    return new Subscription.OP80.DB3011_Work202Action(value);
                case 1201:
                case 1203:
                    return new Subscription.OP71.DB1200_Work01Action(value);
                case 1202:
                case 1204:
                    return new Subscription.OP71.DB1200_Work02Action(value);
                case 1205:
                case 1206:
                    return new Subscription.OP71.DB1200_Work05Action(value);

                default:
                    throw new InvalidOperationException($"未实现的操作编号,DB{position.BlockDb},动作{position.ActionId}");
            }




        }

        private static PLCAction GetOP130ActionInstance(DecodeValue value)
        {
            var position = value.Position;
            switch (position.ActionId)
            {
                case 1:
                    return new Subscription.OP130.DB3011_Work01Action(value);
                default:
                    throw new InvalidOperationException("未实现的操作编号");
            }
        }

        private static PLCAction GetOP20ActionInstance(DecodeValue value)
        {
            var position = value.Position;
            switch (position.ActionId)
            {
                case 1:
                    return new CKS.PLC.Action.Subscription.OP020.OP20SaveDataAction(value);
                case 2:
                    return new Subscription.OP20.DB3031_Work02Action(value);
                case 3:
                    return new Subscription.OP20.DB3031_Work03Action(value);
                //case 4:
                //    return new Subscription.OP20.DB3041_Work04Action(value);
                default:
                    throw new InvalidOperationException("未实现的操作编号");
            }
        }
        private static PLCAction GetOP30ActionInstance(DecodeValue value)
        {
            var position = value.Position;
            switch (position.ActionId)
            {
                case 1:
                    return new Subscription.OP30.DB3011_Work01Action(value);
                case 2:
                    return new Subscription.OP30.DB3021_Work02Action(value);
                case 3:
                case 4: //双通道 
                    return new Subscription.OP30.OP30SaveDataAction(value);
                default:
                    throw new InvalidOperationException("未实现的操作编号");
            }
        }

        private static PLCAction GetOP60ActionInstance(DecodeValue value)
        {
            var position = value.Position;
            switch (position.ActionId)
            {
                case 1:
                    return new Subscription.OP60.DB3031_Work01Action(value);
                case 2:
                    return new Subscription.OP60.DB3031_Work02Action(value);
                default:
                    throw new InvalidOperationException("未实现的操作编号");
            }
        }

        private static PLCAction GetOP70ActionInstance(DecodeValue value)
        {
            var position = value.Position;
            switch (position.ActionId)
            {
                case 1:
                    return new Subscription.OP70.DB3011_Work01Action(value);
                default:
                    throw new InvalidOperationException("未实现的操作编号");
            }
        }



        /// <summary>
        /// 获取零件类型
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public int GetPartType(string code)
        {
            string Prefix = code.Substring(0, 3).ToUpper();
            switch (Prefix)
            {
                case "QXA": return 1;
                case "QXK": return 2;
                case "QXM": return 3;
                case "QXW": return 4;
                case "QXZ": return 5;
                case "QXX": return 6;
                case "QXY": return 7;
                case "QXH": return 8;
                case "QXN": return 9;
                case "QXG": return 10;
                default:
                    throw new Exception($"零件类型未定义 {Prefix}");
            }
        }

        /// <summary>
        /// 推送零件数量变化
        /// 更新当前零件清洗线\缓存线数量，查询子篮零件数量进行统计
        /// </summary>
        /// <param name="PartType"></param>
        public void PushPartCount(int PartType)
        {
            int CleaningLineCount = conn.Select<CksBasket>().Where(a => a.Type == PartType && a.Status == 1).Sum(a => a.Stock).ToInt();
            int CacheLineCount = conn.Select<CksBasket>().Where(a => a.Type == PartType && a.Status == 2).Sum(a => a.Stock).ToInt();
            conn.Update<CksPartCache>()
                .Set(a => a.CleaningLineCount, CleaningLineCount)
                .Set(a => a.CacheLineCount, CacheLineCount)
                .Where(a => a.PartType == PartType)
                .ExecuteAffrows();

            var job = InternalApp.JobProvider.GetService<PushJob>();
            job.UpdateEntraceLine(PartType, CleaningLineCount);
            job.UpdateOutLine(PartType, CacheLineCount);
        }
    }
}
